package com.company.jvm.finalTest;

/**
 * @Classname FinalDomain
 * @Description TODO   final域重排序规则
 * @Date 2021/8/18 15:35
 * @Created by ylr
 */
public class FinalDomain {
    private int a;//普通域
    private final int b;//final域
    private static FinalDomain finalDomain;

    public FinalDomain() {
        this.a = 1;//普通写域
        this.b = 2;//final写域     禁止对final域的写 重排序到构造器之外
        // 在final域写之后，构造函数return之前，插入一个storestore屏障   确保final写对其他处理器可见(刷到了内存)
    }

    public static void writer(){
        finalDomain = new FinalDomain();
    }

    //在一个线程中，初次读对象引用和初次读该对象包含的final域，JMM会禁止这两个操作的重排序。
    //在读一个对象的final域之前，一定会先读这个包含这个final域的对象的引用。
    public static void reader(){
        FinalDomain instance = finalDomain;  //读对象引用
        int a = instance.a;  //读普通域
        int b = instance.b;  //读final域
    }

//    基本数据类型:
//
//    final域写：禁止final域写与构造方法重排序，即禁止final域写重排序到构造方法之外，从而保证该对象对所有线程可见时，
//    该对象的final域全部已经初始化过。
//    final域读：禁止初次读对象的引用与读该对象包含的final域的重排序。
//    引用数据类型：
//    额外增加约束：禁止在构造函数对一个final修饰的对象的成员域的写入与随后将这个被构造的对象的引用赋值给引用变量 重排序
}
